package com.ftx.common.advice;

import com.ftx.common.enums.ErrorCodeEnum;
import com.ftx.common.util.ExceptionUtils;
import com.ftx.common.util.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by fengtingxin on 2019/6/13.
 */
public abstract class BaseAdvice {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * 前置通知
     */
    protected void preNotification(JoinPoint point){
        logger.info("{} --> preNotification 前置通知开始",this.getClass().getSimpleName());
        basePrintLogger(point);
    }



    /**
     * 环绕通知
     */
    protected Object surroundNotification(ProceedingJoinPoint point){
        try{
            logger.info("{} --> surroundNotification 环绕通知开始",this.getClass().getSimpleName());
            basePrintLogger(point);
            return point.proceed();
        }catch (Throwable e){
            logger.error("Exception is {}",e);
            ExceptionUtils.throwBusinessException(ErrorCodeEnum.SYSTEM_BUSY);
        }
        return null;
    }

    /**
     * 后置通知
     */
    protected void postNotification(JoinPoint point){
        logger.info("{} --> postNotification 后置通知开始",this.getClass().getSimpleName());
        basePrintLogger(point);
    }

    /**
     * 异常通知
     */
    protected void abnormalNotification(JoinPoint point){
        logger.info("{} --> abnormalNotification 异常通知开始",this.getClass().getSimpleName());
        basePrintLogger(point);
    }

    /**
     * 最终通知
     */
    protected void finalNotice(JoinPoint point){
        logger.info("{} --> finalNotice 最终通知开始",this.getClass().getSimpleName());
        basePrintLogger(point);
    }


    /**
     * 全都打印出来
     */
    protected void basePrintLogger(JoinPoint point){
        printParam(point.getArgs(),getTargetClassName(point),getTargetMethodName(point));
        logger.info("getTargetClassName is {}",getTargetClassName(point));
        logger.info("getTargetWholeClassName is {}",getTargetWholeClassName(point));
        logger.info("getTargetMethodName is {}",getTargetMethodName(point));
        logger.info("getTargetMethodReturnType is {}",getTargetMethodReturnType(point));
    }

    /**
     * 获取目标类名，不包含包名
     */
    protected String getTargetClassName(JoinPoint point) {
        return getTargetClass(point).getSimpleName();
    }

    /**
     * 获取目标类全名，包含包名
     */
    protected String getTargetWholeClassName(JoinPoint point) {
        return getTargetClass(point).getName();
    }

    /**
     * 获取目标方法名
     */
    protected String getTargetMethodName(JoinPoint point) {
        return getTargetSignature(point).getName();
    }

    /**
     * 获取目标类字节码
     */
    protected Class getTargetClass(JoinPoint point) {
        return point.getTarget().getClass();
    }

    /**
     * 获取目标签名
     */
    protected Signature getTargetSignature(JoinPoint point) {
        return point.getSignature();
    }

    /**
     * 获取目标方法签名
     */
    protected MethodSignature getTargetMethodSignature(JoinPoint point) {
        return (MethodSignature) getTargetSignature(point);
    }

    /**
     * 获取目标方法的返回值类型
     */
    protected Class getTargetMethodReturnType(JoinPoint point) {
        return getTargetMethodSignature(point).getReturnType();
    }


    /**
     * 打印参数
     */
    protected void printParam(Object[] args, String className, String methodName) {
        String paramStr = "{";
        if (args != null && args.length > 0) {
            for (Object arg : args) {
                if (arg == null || StringUtils.isBlank(arg.toString())) {
                    paramStr += "empty,";
                } else {
                    paramStr += arg.toString() + ",";
                }
            }
            //删除最后一个逗号
            if (StringUtils.isNotBlank(paramStr)) {
                paramStr = paramStr.substring(0, paramStr.length() - 1);
            }
        }
        paramStr += "}";
        logger.error("打印入参 {} --> {} request param: {}", className, methodName, paramStr);

    }

}
